home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dbg / sun3.md / dbgMain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  35.2 KB  |  1,371 lines

  1. /* dbgMain.c -
  2.  *
  3.  *     This contains the routines which read and execute commands from kdbx.
  4.  *
  5.  *     All reads and writes to kdbx occur over channel A of the Rs232 line.
  6.  *
  7.  * Copyright (C) 1985 Regents of the University of California
  8.  * All rights reserved.
  9.  */
  10.  
  11. #ifndef lint
  12. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dbg/sun3.md/dbgMain.c,v 9.13 92/09/29 15:52:24 jhh Exp $ SPRITE (Berkeley)";
  13. #endif /* not lint */
  14.  
  15. #include <sprite.h>
  16. #include <dbg.h>
  17. #include <dbgInt.h>
  18. #include <main.h>
  19. #include <mach.h>
  20. #include <proc.h>
  21. #include <vm.h>
  22. #include <vmMach.h>
  23. #include <machMon.h>
  24. #include <net.h>
  25. #include <netEther.h>
  26. #include <netInet.h>
  27. #include <dev.h>
  28. #include <devVid.h>
  29. #include <bstring.h>
  30. #include <string.h>
  31. #include <stdio.h>
  32.  
  33. /*
  34.  * This violates Sprite coding conventions and should be fixed.
  35.  */
  36.  
  37. extern Address vmStackBaseAddr;
  38. extern Address vmStackEndAddr;
  39. extern Address vmBlockCacheBaseAddr;
  40. extern Address vmBlockCacheEndAddr;
  41. extern int VmMachGetKernelContext();
  42. extern void VmMachSetKernelContext();
  43. extern VmMachPTE VmMachGetPageMap();
  44.  
  45.  
  46. Boolean    dbg_BeingDebugged = FALSE;        /* TRUE if are under control
  47.                          * of kdbx.*/
  48. Boolean    dbg_UsingNetwork = FALSE;        /* TRUE if the debugger is
  49.                          * using the network interface*/
  50. char    requestBuffer[DBG_MAX_REQUEST_SIZE];    /* Buffer to receive request
  51.                          * into. */
  52. int    requestOffset;                /* Offset in buffer where next
  53.                          * bytes should be read from.*/
  54. char    replyBuffer[DBG_MAX_REPLY_SIZE];    /* Buffer to hold reply. */
  55. int    replyOffset = 0;            /* Offset in buffer where next
  56.                          * bytes in reply should go. */
  57. int    curMsgNum;                /* The current message that
  58.                          * is being processed. */
  59. int    dbgMonPC;                /* Place to get the PC from
  60.                          * if trap via the monitor.*/
  61. int    dbgTraceLevel;                /* The debugger tracing
  62.                          * level. */
  63. Boolean dbg_SyncedDisks = FALSE;                /* For determining in the
  64.                                                  * debugger whether the disks
  65.                                                  * got sync'd or not. */
  66.  
  67. /*
  68.  * Number of times to poll before timing out and resending (about 2 seconds).
  69.  */
  70. #ifdef sun3
  71. int    dbgTimeout = 50000;
  72. #else
  73. int    dbgTimeout = 15000;
  74. #endif
  75.  
  76. /*
  77.  * Information about the latest packet received.
  78.  */
  79. Boolean            gotPacket;    
  80. int            dbgPacketLength;
  81. Net_InetAddress        dbgMyIPAddr;
  82. Net_InetAddress        dbgSrcIPAddr;
  83. Net_InetAddress        dbgSrcPort;
  84. Net_EtherHdr        dbgEtherHdr;
  85. Net_ScatterGather    dbgGather;
  86. Net_Interface        *dbgInterPtr = (Net_Interface *) NIL;
  87.  
  88. /*
  89.  * Size of debugging packet header and data.
  90.  */
  91. #define    PACKET_HDR_SIZE (sizeof(Net_EtherHdr) + Dbg_PacketHdrSize() + 4)
  92. #define PACKET_DATA_SIZE (DBG_MAX_REPLY_SIZE - PACKET_HDR_SIZE)
  93.  
  94. /*
  95.  * Strings which describe each of the opcodes that kdbx can send us.
  96.  */
  97. static char *opcodeNames[] =  {
  98.     "Read all GPRS",
  99.     "Write GPR",
  100.     "Continue",
  101.     "Single Step",
  102.     "Detach",
  103.     "Inst Read",
  104.     "Inst Write",
  105.     "Data Read",
  106.     "Data Write",
  107.     "Process to walk stack for",
  108.     "Read information after stopped",
  109.     "Return version string",
  110.     "Divert syslog to the console",
  111.     "Reboot the machine",
  112.     "Set up things to start a call command",
  113.     "Clean up things after a call command has executed",
  114.     "UNKNOWN OPCODE"
  115. };
  116.  
  117. /*
  118.  * Strings which describe the different exceptions that can occur.
  119. */
  120. static char *exceptionNames[] = {
  121.   /* 0 */   "Reset",
  122.   /* 1 */   "UNKNOWN EXCEPTION",
  123.   /* 2 */   "Bus Error",
  124.   /* 3 */   "Address Error",
  125.   /* 4 */   "Illegal Instruction",
  126.   /* 5 */   "Zero Div",
  127.   /* 6 */   "CHK Instruction",
  128.   /* 7 */   "TrapV",
  129.   /* 8 */   "Privilege Violation",
  130.   /* 9 */   "Trace Trap",
  131.   /* 10 */  "EMU 1010",
  132.   /* 11 */  "EMU 1111",
  133.   /* 12 */  "UNKNOWN EXCEPTION",
  134.   /* 13 */  "Coprocessor Protocol Violation",
  135.   /* 14 */  "Stack Format Error",
  136.   /* 15 */  "Uninitialized Vector",
  137.   /* 16 */  "UNKNOWN EXCEPTION",
  138.   /* 17 */  "UNKNOWN EXCEPTION",
  139.   /* 18 */  "UNKNOWN EXCEPTION",
  140.   /* 19 */  "UNKNOWN EXCEPTION",
  141.   /* 20 */  "UNKNOWN EXCEPTION",
  142.   /* 21 */  "UNKNOWN EXCEPTION",
  143.   /* 22 */  "UNKNOWN EXCEPTION",
  144.   /* 23 */  "UNKNOWN EXCEPTION",
  145.   /* 24 */  "Spurious Interrupt",
  146.   /* 25 */  "Level 1 Interrupt",
  147.   /* 26 */  "Level 2 Interrupt",
  148.   /* 27 */  "Level 3 Interrupt",
  149.   /* 28 */  "Level 4 Interrupt",
  150.   /* 29 */  "Level 5 Interrupt",
  151.   /* 30 */  "Level 6 Interrupt",
  152.   /* 31 */  "Level 7 Interrupt",
  153.   /* 32 */  "TRAP #0",
  154.   /* 33 */  "Syscall Trap",
  155.   /* 34 */  "Signal Return Trap",
  156.   /* 35 */  "Bad Trap",
  157.   /* 36 */  "TRAP #4",
  158.   /* 37 */  "TRAP #5",
  159.   /* 38 */  "TRAP #6",
  160.   /* 39 */  "TRAP #7",
  161.   /* 40 */  "TRAP #8",
  162.   /* 41 */  "TRAP #9",
  163.   /* 42 */  "TRAP #10",
  164.   /* 43 */  "TRAP #11",
  165.   /* 44 */  "TRAP #12",
  166.   /* 45 */  "TRAP #13",
  167.   /* 46 */  "TRAP #14",
  168.   /* 47 */  "Breakpoint Trap",
  169.   /* 48 */  "FPU Unordered Condition",
  170.   /* 49 */  "FPU Inexact Result",
  171.   /* 50 */  "FPU Zero Divide",
  172.   /* 51 */  "FPU Underflow",
  173.   /* 52 */  "FPU Operand Error",
  174.   /* 53 */  "FPU Overflow",
  175.   /* 54 */  "FPU NaN",
  176.   /* 55 */  "UNKNOWN EXCEPTION",
  177. };
  178.  
  179. /*
  180.  * The type of machine that we are on.
  181.  */
  182. int        machineType;
  183.  
  184. /*
  185.  * Whether syslog should remain diverted on continue or not.
  186.  */
  187. static Boolean    syslogDiverted = FALSE;
  188.  
  189. /*
  190.  * This is a typedef which is used to take care of the hole that is put in
  191.  * the stack when we are called.
  192.  */
  193. typedef struct {
  194.     char    hole[DBG_STACK_HOLE];
  195. } StackHole;
  196.  
  197. /*
  198.  * All of the stuff that is put onto the stack when the debugger is entered.
  199.  */
  200. typedef struct {
  201.     int            gprs[MACH_NUM_GPRS];
  202.     Mach_TrapStack    trapStack;
  203. } DbgStack;
  204.  
  205. /*
  206.  * Declare global variables.
  207.  */
  208. int        dbgSfcReg;
  209. int        dbgDfcReg;
  210. int         dbgUserContext;
  211. int         dbgKernelContext;
  212. DbgStack    dbgGlobalStack;
  213. int        dbgTermReason;
  214. int        dbgInDebugger;
  215. int        dbgIntPending;
  216. int        dbgExcType;
  217. Boolean        dbgPanic;
  218. int        dbgSavedSP;
  219. int        dbgMaxStackAddr;
  220. Boolean        dbg_UsingSyslog = FALSE;
  221. Boolean        dbgCanUseSyslog = TRUE;
  222. static       int    oldContext;
  223.  
  224. /*
  225.  * Saved exception stack stuff.
  226.  */
  227. static    int        savedDbgStackLength;
  228. static    int        savedExcStackLength;
  229. static    DbgStack    savedDbgStack;
  230. static    Boolean        callInProgress = FALSE;
  231.  
  232. /* 
  233.  * Forward declarations:
  234.  */
  235. static void DbgCheckNmis _ARGS_((void));
  236. static char *    TranslateOpcode _ARGS_((Dbg_Opcode opcode));
  237. static char *    TranslateException _ARGS_((int exception));
  238. static Boolean    ReadRequest _ARGS_((Boolean timeout));
  239. static void    SendReply _ARGS_((void));
  240. static void    GetRequestBytes _ARGS_((int numBytes, Address dest));
  241. static void    PutReplyBytes _ARGS_((int numBytes, Address src));
  242.  
  243. extern    void    Dbg_Main _ARGS_((StackHole stackHole,
  244.                  DbgStack dbgStack));
  245.                 /* called from assembly code? */
  246.  
  247. /*
  248.  * ----------------------------------------------------------------------------
  249.  *
  250.  * DbgCheckNmis --
  251.  *
  252.  *    Turn Non-maskable-interrupts on and off to allow keyboard events to
  253.  *    take place.  Only needed on Sun-2's because of the funny mapping
  254.  *    between kernel and user address spaces - they are turned on in the
  255.  *    main debugging loop on Sun-3's.
  256.  *
  257.  * Results:
  258.  *     None.
  259.  *
  260.  * Side effects:
  261.  *     None.
  262.  *
  263.  * ----------------------------------------------------------------------------
  264.  */
  265. static void
  266. DbgCheckNmis()
  267. {
  268. #ifdef sun2
  269.     int    oldContext;
  270.     oldContext = VmMachGetKernelContext(); 
  271.     VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  272.     Mach_MonStartNmi();
  273.     Mach_MonStopNmi();
  274.     VmMachSetKernelContext(oldContext);
  275. #endif
  276. }
  277.  
  278.  
  279. /*
  280.  * ----------------------------------------------------------------------------
  281.  *
  282.  * Dbg_InRange --
  283.  *
  284.  *     Return true if the given address is a valid kernel address and false
  285.  *     otherwise.
  286.  *
  287.  * Results:
  288.  *     True if the given address is a valid kernel address and false
  289.  *     otherwise.
  290.  *
  291.  * Side effects:
  292.  *     None.
  293.  *
  294.  * ----------------------------------------------------------------------------
  295.  */
  296. Boolean Dbg_InRange(addr, numBytes, writeable) 
  297.     unsigned     int addr;     /* Beginning address to check. */
  298.     int        numBytes;     /* Number of bytes to check. */
  299.     Boolean    writeable;    /* TRUE => address must be writeable. */
  300. {
  301.     VmMachPTE        pte;
  302.     int            i;
  303.     unsigned    int    prot;
  304.     int            firstPage;
  305.     int            lastPage;
  306.     unsigned    int    maxAddr;
  307.  
  308. #ifdef sun2
  309.     maxAddr = 0x1000000;
  310. #else
  311.     /*
  312.      * Don't look at anything in device space. 
  313.      */
  314.     maxAddr = 0x10000000;
  315. #endif
  316.     if (addr > maxAddr || (addr + numBytes - 1) > maxAddr) {
  317.     return(FALSE);
  318.     }
  319.     /*
  320.      * Don't look at anything in device space. 
  321.      */
  322.     if (!(((addr + numBytes - 1) < VMMACH_DEV_START_ADDR) ||
  323.      (addr >= VMMACH_DMA_START_ADDR))) {
  324.     return FALSE;
  325.     }
  326.     if ((int) (addr) & 0x1) {
  327.     printf("Dbg: odd address: %x\n", addr);
  328.     return(FALSE);
  329.     }
  330.  
  331.     firstPage = ((unsigned int) addr) >> VMMACH_PAGE_SHIFT;
  332.     lastPage = (((unsigned int) addr) + numBytes - 1) >> VMMACH_PAGE_SHIFT;
  333.     for (i = firstPage; i <= lastPage; i++) {
  334.     pte = VmMachGetPageMap((Address)(i << VMMACH_PAGE_SHIFT));
  335.     prot = pte & VMMACH_PROTECTION_FIELD;
  336.     if (!(pte & VMMACH_RESIDENT_BIT)) {
  337.         return(FALSE);
  338.     } else if (writeable) {
  339.         if (prot != VMMACH_KRW_PROT && prot != VMMACH_URW_PROT) {
  340.         return(FALSE);
  341.         }
  342.     } else {
  343.         if (prot != VMMACH_KRW_PROT && prot != VMMACH_URW_PROT &&
  344.         prot != VMMACH_KR_PROT && prot != VMMACH_UR_PROT) {
  345.         return(FALSE);
  346.         }
  347.     }
  348.     }
  349.  
  350.     return(TRUE);
  351. }
  352.  
  353.  
  354. /*
  355.  * ----------------------------------------------------------------------------
  356.  *
  357.  * TranslateOpcode --
  358.  *
  359.  *     Return the string which describes the given opcode.
  360.  *
  361.  * Results:
  362.  *     The string which describes the given opcode.
  363.  *
  364.  * Side effects:
  365.  *     None.
  366.  *
  367.  * ----------------------------------------------------------------------------
  368.  */
  369. static char *
  370. TranslateOpcode(opcode)
  371.     Dbg_Opcode opcode;        /* The opcode which is to be translated. */
  372. {
  373.     int index;
  374.  
  375.     index = (int) opcode;
  376.     if (index < 0 || index > (int) DBG_UNKNOWN) {
  377.         index = (int) DBG_UNKNOWN;
  378.     }
  379.  
  380.     return(opcodeNames[index]);
  381. }
  382.  
  383.  
  384. /*
  385.  * ----------------------------------------------------------------------------
  386.  *
  387.  * TranslateException --
  388.  *
  389.  *     Return the string that describes the given exception.
  390.  *
  391.  * Results:
  392.  *     None.
  393.  *
  394.  * Side effects:
  395.  *     None.
  396.  *
  397.  * ----------------------------------------------------------------------------
  398.  */
  399. static char *
  400. TranslateException(exception)
  401.     int exception;        /* The exception which is to be translated. */
  402. {
  403.  
  404.     if (exception < 0 || exception > MACH_UNKNOWN_EXC) {
  405.         exception = MACH_UNKNOWN_EXC;
  406.     }
  407.  
  408.     return(exceptionNames[exception]);
  409. }
  410.  
  411.  
  412. /*
  413.  * ----------------------------------------------------------------------------
  414.  *
  415.  * DbgComplain --
  416.  *
  417.  *     Complain because we are already in the debugger.
  418.  *
  419.  * Results:
  420.  *     None.
  421.  *
  422.  * Side effects:
  423.  *     None.
  424.  *
  425.  * ----------------------------------------------------------------------------
  426.  */
  427. void
  428. DbgComplain(trapStack)
  429.     Mach_TrapStack    trapStack;
  430. {
  431.     printf("%s exception in the debugger at pc %x addr %x\n",
  432.        TranslateException(trapStack.trapType), 
  433.        trapStack.excStack.pc,
  434.        trapStack.excStack.tail.addrBusErr.faultAddr);
  435.     Mach_MonAbort();
  436. }
  437.  
  438.  
  439. /*
  440.  * ----------------------------------------------------------------------------
  441.  *
  442.  * Dbg_Init --
  443.  *
  444.  *     Initialize the debugger.
  445.  *
  446.  * Results:
  447.  *     None.
  448.  *
  449.  * Side effects:
  450.  *     dbgMonPC and dbgDoTrace are initialized.
  451.  *
  452.  * ----------------------------------------------------------------------------
  453.  */
  454. void
  455. Dbg_Init()
  456. {
  457.     dbgMonPC = 0;
  458.     dbgTraceLevel = 0;
  459.     dbgInDebugger = 0;
  460.     dbgIntPending = 0;
  461.     dbgPanic = FALSE;
  462.     dbg_BeingDebugged = FALSE;
  463.     machineType = Mach_GetMachineType();
  464.     Mach_MonPrintf("Machine type %d\n", machineType);
  465. }
  466.  
  467.  
  468. /*
  469.  * ----------------------------------------------------------------------------
  470.  *
  471.  * Dbg_InputPacket --
  472.  *
  473.  *     See if the current packet is for us.  At the moment this only 
  474.  *    handles ethernet packets.
  475.  *
  476.  *
  477.  * Results:
  478.  *     None.
  479.  *
  480.  * Side effects:
  481.  *     gotPacket is set to true if we got a packet that we liked.
  482.  *
  483.  * ----------------------------------------------------------------------------
  484.  */
  485. void
  486. Dbg_InputPacket(interPtr, packetPtr, packetLength)
  487.     Net_Interface    *interPtr;
  488.     Address        packetPtr;
  489.     int            packetLength;
  490. {
  491.     Address    dataPtr;
  492.     int        dataLength;
  493.     Net_EtherHdr    *etherHdrPtr;
  494.  
  495.     if (interPtr->netType != NET_NETWORK_ETHER) {
  496.     return;
  497.     }
  498.     etherHdrPtr = (Net_EtherHdr *)packetPtr;
  499.     if (etherHdrPtr->type != NET_ETHER_IP) {
  500.     if (dbgTraceLevel >= 5) {
  501.         printf("Non-IP (Type=0x%x) ", (int)etherHdrPtr->type);
  502.     }
  503.     return;
  504.     }
  505.     if (gotPacket) {
  506.     if (dbgTraceLevel >= 4) {
  507.         printf("Already have a packet.\n");
  508.     }
  509.     return;
  510.     }
  511.     if (dbgTraceLevel >= 4) {
  512.     printf("Validating packet\n");
  513.     }
  514.     if (Dbg_ValidatePacket(packetLength - sizeof(Net_EtherHdr),
  515.                (Net_IPHeader *)(packetPtr + sizeof(Net_EtherHdr)),
  516.                &dataLength, &dataPtr,
  517.                &dbgMyIPAddr, &dbgSrcIPAddr, &dbgSrcPort)) {
  518.     if (dbgTraceLevel >= 4) {
  519.         printf("Got a packet: length=%d\n", dataLength);
  520.     }
  521.     bcopy((Address)etherHdrPtr, (Address)&dbgEtherHdr,
  522.         sizeof(Net_EtherHdr));
  523.     gotPacket = TRUE;
  524.     bcopy(dataPtr, requestBuffer, dataLength);
  525.     /*
  526.      * Set the interface we are using. 
  527.      */
  528.     dbgInterPtr = interPtr;
  529.     }
  530. }
  531.  
  532.  
  533. /*
  534.  * ----------------------------------------------------------------------------
  535.  *
  536.  * ReadRequest --
  537.  *
  538.  *     Read the next request from kdbx.
  539.  *
  540.  * Results:
  541.  *     None.
  542.  *
  543.  * Side effects:
  544.  *     TRUE if didn't time out.
  545.  *
  546.  * ----------------------------------------------------------------------------
  547.  */
  548. static Boolean
  549. ReadRequest(timeout)
  550.     Boolean    timeout;    /* TRUE if should timeout after waiting a 
  551.                  * while. */
  552. {
  553.     int    timeOutCounter;
  554.     Net_Interface    *interPtr;
  555.     int        i;
  556.  
  557.     gotPacket = FALSE;
  558.     timeOutCounter = dbgTimeout;
  559.     do {
  560.         DbgCheckNmis();
  561.         /*
  562.          * Listen on all the interfaces. The debugger is relatively
  563.          * stateless so its easiest to just listen on them all.
  564.          */
  565.         for (i = 0; ; i++) {
  566.         interPtr = Net_NextInterface(TRUE, &i);
  567.         if (interPtr == (Net_Interface *) NIL) {
  568.             break;
  569.         }
  570.         Net_RecvPoll(interPtr);
  571.         if (gotPacket) {
  572.             break;
  573.         }
  574.         }
  575.         if (timeout) {
  576.         timeOutCounter--;
  577.         }
  578.     } while(!gotPacket && timeOutCounter != 0);
  579.     if (gotPacket) {
  580.         replyOffset = PACKET_HDR_SIZE;
  581.         requestOffset = 4;
  582.         curMsgNum = *(int *)(requestBuffer);
  583.         if (dbgTraceLevel >= 4) {
  584.         printf("MsgNum = %d\n", curMsgNum);
  585.         }
  586.     }
  587.  
  588.     return(gotPacket);
  589. }
  590.  
  591.  
  592. /*
  593.  * ----------------------------------------------------------------------------
  594.  *
  595.  * GetRequestBytes --
  596.  *
  597.  *     Get the next numBytes bytes from the current request.
  598.  *
  599.  * Results:
  600.  *     None.
  601.  *
  602.  * Side effects:
  603.  *     None.
  604.  *
  605.  * ----------------------------------------------------------------------------
  606.  */
  607. static void
  608. GetRequestBytes(numBytes, dest)
  609.     int        numBytes;
  610.     Address    dest;
  611. {
  612.     bcopy(requestBuffer + requestOffset, dest, numBytes);
  613.     requestOffset += numBytes;
  614. }
  615.  
  616.  
  617. /*
  618.  * ----------------------------------------------------------------------------
  619.  *
  620.  * PutReplyBytes --
  621.  *
  622.  *     Put the given bytes into the reply buffer.
  623.  *
  624.  * Results:
  625.  *     None.
  626.  *
  627.  * Side effects:
  628.  *     None.
  629.  *
  630.  * ----------------------------------------------------------------------------
  631.  */
  632. static void
  633. PutReplyBytes(numBytes, src)
  634.     int        numBytes;
  635.     Address    src;
  636. {
  637.     if (replyOffset + numBytes > DBG_MAX_REPLY_SIZE) {
  638.     printf("PutReplyBytes: Buffer overflow\n");
  639.     numBytes = DBG_MAX_REPLY_SIZE - replyOffset;
  640.     }
  641.     bcopy(src, &replyBuffer[replyOffset], numBytes);
  642.     replyOffset += numBytes;
  643. }
  644.  
  645.  
  646. /*
  647.  * ----------------------------------------------------------------------------
  648.  *
  649.  * SendReply --
  650.  *
  651.  *     Send a reply to kdbx.
  652.  *
  653.  * Results:
  654.  *     None.
  655.  *
  656.  * Side effects:
  657.  *     None.
  658.  *
  659.  * ----------------------------------------------------------------------------
  660.  */
  661. static void
  662. SendReply()
  663. {
  664.     Net_EtherHdr        *etherHdrPtr;
  665.  
  666.     if (dbgTraceLevel >= 4) {
  667.         printf("Sending reply\n");
  668.     }
  669.     etherHdrPtr = (Net_EtherHdr *) replyBuffer;
  670.     etherHdrPtr->source = dbgEtherHdr.destination;
  671.     etherHdrPtr->destination = dbgEtherHdr.source;
  672.     etherHdrPtr->type = dbgEtherHdr.type;
  673.     dbgGather.bufAddr = replyBuffer + sizeof(Net_EtherHdr);
  674.     dbgGather.length = replyOffset - sizeof(Net_EtherHdr);
  675.     dbgGather.mutexPtr = (Sync_Semaphore *) NIL;
  676.     *(int *)(replyBuffer + PACKET_HDR_SIZE - 4) = curMsgNum;
  677.     Dbg_FormatPacket(dbgMyIPAddr, dbgSrcIPAddr, dbgSrcPort,
  678.              replyOffset - sizeof(Net_EtherHdr) - Dbg_PacketHdrSize(),
  679.              replyBuffer + sizeof(Net_EtherHdr));
  680.     (void) Net_RawOutput(dbgInterPtr, (Address) etherHdrPtr, &dbgGather, 1);
  681.     if (dbgTraceLevel >= 4) {
  682.         printf("Sent reply\n");
  683.     }
  684. }
  685.  
  686. /*
  687.  * 68020 and 68010 moveml instructions work differently.  68010 stores
  688.  * original value of sp and 68020 stores sp - 4.  This has to be fixed
  689.  * when getting around the exception stack.
  690.  */
  691. #ifdef sun3
  692. #define STACK_INC    4
  693. #endif
  694. #ifdef sun2
  695. #define STACK_INC    0
  696. #endif
  697.  
  698. /*
  699.  * ----------------------------------------------------------------------------
  700.  *
  701.  * Dbg_Main --
  702.  *
  703.  *     The main debugger loop.  This will read commands from the rs232 line
  704.  *     and call the proper routine to execute them.
  705.  *
  706.  * Results:
  707.  *     None.
  708.  *
  709.  * Side effects:
  710.  *     None.
  711.  *
  712.  * ----------------------------------------------------------------------------
  713.  */
  714. /*ARGSUSED*/
  715. void
  716. Dbg_Main(stackHole, dbgStack)
  717.     StackHole        stackHole;    /* The hole put in the stack so that
  718.                      * kdbx can play around with the stack*/
  719.     DbgStack        dbgStack;    /* All of the stuff that is put onto the
  720.                      * stack because of the exception and
  721.                      * the trap handler. */
  722. {
  723.     short        trapCode;    /* Reason that we trapped that is sent
  724.                      * to kdbx. */
  725.     Boolean          done;        /* Boolean to tell us whether to leave
  726.                      * the main debugger loop */
  727.     int              dbgStackLength;/* The length of the trap stack */
  728.     int              excStackLength;    /* The length of the exception part 
  729.                      * of the trap stack */
  730.     Dbg_Opcode          opcode;        /* The operation that was requested */
  731.     short          tOpcode;    /* Temporary used to receive the opcode
  732.                      * which is sent as a short. */
  733.                     /* Process table entry that we switched
  734.                      * stacks to. */
  735.     Proc_ControlBlock    *procPtr = (Proc_ControlBlock *) NIL;
  736.     Boolean        atInterruptLevel;/* TRUE if we were entered from an
  737.                       * interrupt handler. */
  738.  
  739. #ifdef sun3
  740.     /*
  741.      * Turn on non-maskable interrupts.
  742.      */
  743.     Mach_MonStartNmi();
  744. #endif
  745.     /*
  746.      * Switch to kernel context so that we can access the monitor.
  747.      */
  748.     oldContext = VmMachGetKernelContext();
  749.     VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  750.  
  751. #ifdef NOTDEF
  752. /*
  753.  * This code causes machines to seem to pop out of the debugger.
  754.  */
  755.     if (!dbg_BeingDebugged) {
  756.         /*
  757.          * Try to sync the disks if we aren't at interrupt level.  If we
  758.          * are don't bother because we'll just hang waiting for interrupts.
  759.          * Of course I could force interrupts to be enabled but I'm not sure
  760.          * if that's a great idea.
  761.          */
  762.         if (mach_NumDisableIntrsPtr[0] == 0 && !mach_AtInterruptLevel) {
  763.             Mach_EnableIntr();
  764.             Sys_SyncDisks(!MACH_BRKPT_TRAP);
  765.             dbg_SyncedDisks = TRUE;
  766.             Mach_DisableIntr();
  767.         }
  768.     }
  769. #endif NOTDEF
  770.  
  771.     /*
  772.      * Put us at interrupt level so that printf won't accidently enable
  773.      * interrupts.
  774.      */
  775.     atInterruptLevel = mach_AtInterruptLevel;
  776.     mach_AtInterruptLevel = TRUE;
  777.  
  778.  
  779.     /*
  780.      * Force system log output to the console.
  781.      */
  782.     if (!syslogDiverted) {
  783.     Dev_SyslogDebug(TRUE);
  784.     }
  785.  
  786.     /*
  787.      * We want to inform the user what caused the problem.  However we only
  788.      * tell him if: 1) we are debugging the debugger; 2) we are not under 
  789.      * debugger control (i.e. we don't want to inform the user on every trace 
  790.      * trap), 3) we got something besides a trace trap or a breakpoint trap
  791.      * exception.
  792.      */
  793.     if (dbgTraceLevel >= 1 || !dbg_BeingDebugged || 
  794.         (dbgStack.trapStack.trapType != MACH_TRACE_TRAP && 
  795.          dbgStack.trapStack.trapType != MACH_BRKPT_TRAP)) { 
  796.     Dev_VidEnable(TRUE);    /* unblank the screen */
  797.     printf("Entering debugger with a %s exception at PC 0x%x\r\n",
  798.            TranslateException(dbgStack.trapStack.trapType),
  799.            (unsigned) dbgStack.trapStack.excStack.pc);
  800.     }
  801.  
  802.     /*
  803.      * The saved stack pointer points to all of the junk on the stack from
  804.      * the exception.  We need to move the saved stack pointer past all of
  805.      * this junk to the point where kdbx sees what it expects (it doesn't 
  806.      * understand exception stacks).  Also we need to copy all of the 
  807.      * trap stack to a global variable.  This allows access to this stack 
  808.      * through the debugger (kdbx doesn't know we are in this routine so the
  809.      * parameter dbgStack cannot be printed out in kdbx).
  810.      *
  811.      * NOTE:
  812.      *
  813.      * When kdbx does a "call" command it adds things onto the stack starting 
  814.      * from the saved stack pointer.  When it does this it will trash the 
  815.      * trap stack that we were passed.  Thus saving a copy of the trap
  816.      * stack also serves the purpose of preventing kdbx from trashing the
  817.      * original copy.
  818.      */
  819.     excStackLength = Mach_GetExcStackSize(&dbgStack.trapStack.excStack);
  820.     dbgStackLength = sizeof(DbgStack) - sizeof(Mach_ExcStack) + excStackLength;
  821.  
  822.     bcopy((Address) &dbgStack, (Address) &dbgGlobalStack, dbgStackLength);
  823.  
  824.     dbgGlobalStack.gprs[SP] += excStackLength + STACK_INC + 
  825.                    MACH_TRAP_INFO_SIZE;
  826.  
  827.     /*
  828.      * Clear the trace bit from the status register.
  829.      */
  830.     dbgGlobalStack.trapStack.excStack.statusReg &= ~MACH_SR_TRACEMODE;
  831.  
  832.     /*
  833.      * We need to tell kdbx what type of exception this is.  If the
  834.      * termReason is DBG_INTERRUPT_SIG then we set the trap code to
  835.      * interrupted.  Otherwise we don't know what caused us to get here so
  836.      * we have to check the exception type.  If the exception is either a
  837.      * trace trap of a breakpoint trap then we set the term reason to
  838.      * DBG_TRACE_TRAP_SIG and set the trap code appropriately.  Otherwise we 
  839.      * tell kdbx that the reason was an DBG_INTERRUPT_SIG and we set the trap
  840.      * code appropriately for the given exception.
  841.      */
  842.     trapCode = dbgStack.trapStack.trapType;
  843.     if (dbgTermReason == DBG_INTERRUPT_SIG) {
  844.     trapCode = DBG_INTERRUPT;
  845.     } else if (dbgPanic) {
  846.     dbgPanic = FALSE;
  847.     trapCode = DBG_INTERRUPT;
  848.         dbgTermReason = DBG_INTERRUPT_SIG;
  849.     } else if (dbgStack.trapStack.trapType == MACH_TRACE_TRAP ||
  850.            dbgStack.trapStack.trapType == MACH_BRKPT_TRAP) {
  851.     dbgTermReason = DBG_TRACE_TRAP_SIG;
  852.     } else {
  853.     dbgTermReason = DBG_INTERRUPT_SIG;
  854.     }
  855.  
  856.     dbg_UsingNetwork = TRUE;
  857.  
  858.     /*
  859.      * If we are stopped after a continue or single step must write a
  860.      * null byte to the debugger at the other end.  It knows that if it sees
  861.      * a null byte we are stopped at this end.
  862.      */
  863.     if (dbg_BeingDebugged) {
  864.     unsigned    char    ch;
  865.  
  866.     ch = 0;
  867.     PutReplyBytes(1, (Address)&ch);
  868.     SendReply();
  869.     do {
  870.         if (ReadRequest(TRUE)) {
  871.         GetRequestBytes(2, (Address)&tOpcode);
  872.         opcode = (Dbg_Opcode) tOpcode;
  873.         if (opcode == DBG_GET_STOP_INFO) {
  874.             break;
  875.         }
  876.         }
  877.         /*
  878.          * We can only timeout if we are using network debugging.
  879.          */
  880.         (void) Net_RawOutput(dbgInterPtr, (Address) replyBuffer, 
  881.             &dbgGather, 1);
  882.         if (dbgTraceLevel >= 5) {
  883.         printf("DBG: Timeout\n");
  884.         }
  885.         printf("TI ");
  886.     } while (TRUE);
  887.     } else {
  888.     (void) ReadRequest(FALSE);
  889.     GetRequestBytes(2, (Address)&tOpcode);
  890.     opcode = (Dbg_Opcode) tOpcode;
  891.     }
  892.  
  893.     /*
  894.      * Now read commands until kdbx tells us that we can return.
  895.      */
  896.     done = FALSE;
  897.     while (!done) {
  898.     if (dbgTraceLevel >= 2) {
  899.         printf("Request: %s ", TranslateOpcode(opcode));
  900.     }
  901.  
  902.     /*
  903.      * Process the request 
  904.      */
  905.     switch (opcode) {
  906.  
  907.         /*
  908.          * The client wants to read some data from us ...
  909.          */
  910.  
  911.         case DBG_GET_STOP_INFO: {
  912.         StopInfo    stopInfo;
  913.         extern void    Mach_ContextSwitch();
  914.         stopInfo.codeStart = (int)mach_CodeStart;
  915.         if (procPtr != (Proc_ControlBlock *) NIL &&
  916.             procPtr->machStatePtr != (Mach_State *)NIL) {
  917.             stopInfo.maxStackAddr =
  918.             (int)(procPtr->machStatePtr->kernStackStart + 
  919.                   mach_KernStackSize);
  920.             bcopy((Address) procPtr->machStatePtr->switchRegs,
  921.                 (Address) stopInfo.genRegs,
  922.                 sizeof(procPtr->machStatePtr->switchRegs));
  923.             stopInfo.pc = (int) ((Address) Mach_ContextSwitch);
  924.         } else {
  925.             stopInfo.maxStackAddr = dbgMaxStackAddr;
  926.             bcopy((Address) dbgGlobalStack.gprs, 
  927.                 (Address) stopInfo.genRegs,
  928.                 sizeof(dbgGlobalStack.gprs));
  929.             stopInfo.pc = dbgGlobalStack.trapStack.excStack.pc;
  930.         }
  931.         stopInfo.termReason = dbgTermReason;
  932.         stopInfo.trapCode = trapCode;
  933.         stopInfo.statusReg = 
  934.         (unsigned short) dbgGlobalStack.trapStack.excStack.statusReg;
  935.         PutReplyBytes(sizeof(stopInfo), (Address)&stopInfo);
  936.         SendReply();
  937.         break;
  938.         }
  939.         case DBG_READ_ALL_GPRS:
  940.         if (procPtr != (Proc_ControlBlock *) NIL &&
  941.             procPtr->machStatePtr != (Mach_State *)NIL) {
  942.             PutReplyBytes(sizeof(procPtr->machStatePtr->switchRegs),
  943.                  (Address) procPtr->machStatePtr->switchRegs);
  944.         } else {
  945.             PutReplyBytes(sizeof(dbgGlobalStack.gprs),
  946.                      (Address) dbgGlobalStack.gprs);
  947.         }
  948.         SendReply();
  949.         break;
  950.  
  951.         case DBG_GET_DUMP_BOUNDS: {
  952.         Dbg_DumpBounds bounds;
  953.         extern unsigned int end;
  954.         bounds.pageSize = vm_PageSize;
  955.         bounds.stackSize = mach_KernStackSize;
  956.         bounds.kernelCodeStart = (unsigned int) mach_KernStart;
  957.         bounds.kernelCodeSize  = 
  958.             (unsigned int) (((Address)(&end)) - mach_KernStart);
  959.         bounds.kernelDataStart    = ((unsigned int)(&end));
  960.         bounds.kernelDataSize    = (unsigned int) 
  961.                 (vmMemEnd - ((Address)(&end)));
  962.         bounds.kernelStacksStart = (unsigned int)vmStackBaseAddr;
  963.         bounds.kernelStacksSize = (unsigned int) 
  964.                 (vmStackEndAddr - vmStackBaseAddr);
  965.         bounds.fileCacheStart    = (unsigned int)vmBlockCacheBaseAddr;
  966.         bounds.fileCacheSize    = (unsigned int) (vmBlockCacheEndAddr - 
  967.                         vmBlockCacheBaseAddr);
  968.  
  969.         PutReplyBytes(sizeof(bounds), (char *)&bounds);
  970.         SendReply();
  971.         break;
  972.         }
  973.         
  974.         case DBG_GET_VERSION_STRING: {
  975.         char    *version;
  976.  
  977.         version = SpriteVersion();
  978.         PutReplyBytes(strlen(version) + 1, version);
  979.         SendReply();
  980.         break;
  981.         }
  982.         case DBG_INST_READ:
  983.         case DBG_DATA_READ: {
  984.         Dbg_ReadMem    readMem;
  985.         int        status;
  986.  
  987.         GetRequestBytes(sizeof(readMem), (Address) &readMem); 
  988.         if (dbgTraceLevel >= 2) {
  989.             printf("Addr=%x Numbytes=%d ",
  990.                 readMem.address, readMem.numBytes);
  991.         }
  992.  
  993.         VmMachSetKernelContext(oldContext);
  994.         if (Dbg_InRange((unsigned int) readMem.address, readMem.numBytes,
  995.                 FALSE)) {
  996.             status = 1;
  997.             PutReplyBytes(sizeof(status), (Address)&status);
  998.             PutReplyBytes(readMem.numBytes, (Address)readMem.address);
  999.         } else {
  1000.             if (dbgTraceLevel >= 2) {
  1001.             printf("FAILURE ");
  1002.             }
  1003.             status = 0;
  1004.             PutReplyBytes(sizeof(status), (Address)&status);
  1005.         }
  1006.         VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  1007.         SendReply();
  1008.         break;
  1009.         }
  1010.  
  1011.         /*
  1012.          * The client wants to write something to us.
  1013.          */
  1014.         case DBG_SET_PID: {
  1015.         Proc_PID    pid;
  1016.  
  1017.         GetRequestBytes(sizeof(pid), (Address) &pid);
  1018.         {
  1019.             int    dummy;
  1020.  
  1021.             PutReplyBytes(4, (Address) &dummy);
  1022.             SendReply();
  1023.         }
  1024.         if (dbgTraceLevel >= 2) {
  1025.             printf("pid %x ", pid);
  1026.         }
  1027.         if (pid == 0) {
  1028.             procPtr = (Proc_ControlBlock *) NIL;
  1029.         } else {
  1030.             procPtr = Proc_GetPCB(pid);
  1031.             if (procPtr == (Proc_ControlBlock *) NIL ||
  1032.                 procPtr == (Proc_ControlBlock *) 0 ||
  1033.             procPtr->state == PROC_UNUSED ||
  1034.                 procPtr->state == PROC_DEAD ||
  1035.             procPtr->state == PROC_NEW) {
  1036.             printf("Can't backtrace stack for process %x\n",
  1037.                     pid);
  1038.             procPtr = (Proc_ControlBlock *) NIL;
  1039.             }
  1040.         }
  1041.         break;
  1042.         }
  1043.         case DBG_REBOOT: {
  1044.         int    stringLength;
  1045.         char    rebootString[100];
  1046.         /*
  1047.          * For a reboot command first read the size of the string and
  1048.          * then the string itself.
  1049.          */
  1050.         GetRequestBytes(sizeof(int), (Address)&stringLength);
  1051.         if (stringLength != 0) {
  1052.             GetRequestBytes(stringLength, (Address)rebootString);
  1053.         }
  1054.         rebootString[stringLength] = '\0';
  1055.         {
  1056.             int    dummy;
  1057.  
  1058.             PutReplyBytes(4, (Address) &dummy);
  1059.             SendReply();
  1060.         }
  1061.         Mach_MonReboot(rebootString);
  1062.         }
  1063.         case DBG_INST_WRITE:
  1064.         case DBG_DATA_WRITE: {
  1065.         Dbg_WriteMem        writeMem;
  1066.         unsigned    char    ch;
  1067.         /*
  1068.          * For an instruction or a data write we first have to find out 
  1069.          * which address to write to and how many bytes to write.  Next
  1070.          * we have to make sure that the address is valid.  If it is
  1071.          * then we read the data and write it to the given address.  If
  1072.          * not we just report an error to kdbx.
  1073.          */
  1074.         GetRequestBytes(2 * sizeof(int), (Address) &writeMem);
  1075.         if (dbgTraceLevel >= 2) {
  1076.             printf("Addr=%x Numbytes=%d ",
  1077.                 writeMem.address, writeMem.numBytes);
  1078.         }
  1079.  
  1080.         VmMachSetKernelContext(oldContext);
  1081.         if (Dbg_InRange((unsigned int) writeMem.address,
  1082.                 writeMem.numBytes, opcode == DBG_DATA_WRITE)) {
  1083.             if (opcode == DBG_INST_WRITE) {
  1084.             VmMach_SetProtForDbg(TRUE, writeMem.numBytes, 
  1085.                          (Address)writeMem.address);
  1086.             }
  1087.             GetRequestBytes(writeMem.numBytes,
  1088.                     (Address) writeMem.address);
  1089.             if (opcode == DBG_INST_WRITE) {
  1090.             VmMach_SetProtForDbg(FALSE, writeMem.numBytes, 
  1091.                          (Address)writeMem.address);
  1092.             }
  1093.             ch = 1;
  1094.         } else {
  1095.             char    buf[100];
  1096.  
  1097.             if (dbgTraceLevel >= 2) {
  1098.             printf("FAILURE ");
  1099.             }
  1100.             GetRequestBytes(writeMem.numBytes, buf);
  1101.             ch = 0;
  1102.         }
  1103.         VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  1104.  
  1105.         PutReplyBytes(1, (char *) &ch);
  1106.         SendReply();
  1107.  
  1108.         break;
  1109.         }
  1110.  
  1111.         case DBG_WRITE_GPR: {                
  1112.         Dbg_WriteGPR    writeGPR;
  1113.  
  1114.         /*
  1115.          * First find out which register is being written and
  1116.          * then read the value.
  1117.          */
  1118.         GetRequestBytes(sizeof(writeGPR), (Address)&writeGPR);
  1119.         {
  1120.             int    dummy;
  1121.  
  1122.             PutReplyBytes(4, (Address) &dummy);
  1123.             SendReply();
  1124.         }
  1125.         if (dbgTraceLevel >= 2) {
  1126.             printf("register %d data %x ", writeGPR.regNum, 
  1127.                 writeGPR.regVal);
  1128.         }
  1129.         dbgGlobalStack.gprs[writeGPR.regNum] = writeGPR.regVal;
  1130.         break;
  1131.         }
  1132.  
  1133.         case DBG_DIVERT_SYSLOG: 
  1134.         GetRequestBytes(sizeof(Boolean), (Address)&syslogDiverted);
  1135.         {
  1136.             int    dummy;
  1137.  
  1138.             PutReplyBytes(4, (Address) &dummy);
  1139.             SendReply();
  1140.         }
  1141.         break;
  1142.  
  1143.         case DBG_BEGIN_CALL:
  1144.         /*
  1145.          * We are beginning a call command.  Fix up the stack
  1146.          * so that we will be able to continue.  We will put
  1147.          * it back when we are done.
  1148.          */
  1149.         savedDbgStackLength = dbgStackLength;
  1150.         savedExcStackLength = excStackLength;
  1151.         bcopy((Address)&dbgGlobalStack, (Address)&savedDbgStack,
  1152.             dbgStackLength);
  1153.  
  1154.         dbgGlobalStack.trapStack.excStack.vor.stackFormat = MACH_SHORT;
  1155.         excStackLength =
  1156.             Mach_GetExcStackSize(&dbgGlobalStack.trapStack.excStack);
  1157.         dbgStackLength = excStackLength + sizeof(DbgStack) - 
  1158.                  sizeof(Mach_ExcStack);
  1159.  
  1160.         callInProgress = TRUE;
  1161.         if (dbgCanUseSyslog) {
  1162.             dbg_UsingSyslog = TRUE;
  1163.         }
  1164.           {
  1165.             int    dummy;
  1166.  
  1167.             PutReplyBytes(4, (Address) &dummy);
  1168.             SendReply();
  1169.         }
  1170.  
  1171.         break;
  1172.         case DBG_END_CALL: {
  1173.         char    *buffer;
  1174.         int    *firstIndexPtr;
  1175.         int    *lastIndexPtr;
  1176.         int    bufSize;
  1177.         int    length;
  1178.         if (callInProgress) {
  1179.             /*
  1180.              * Restore the state to the state before the
  1181.              * call was begun.  Note that the DBG_END_CALL command will
  1182.              * be executed until the sys log buffer is empty so only
  1183.              * need to restore our state if the callInProgress flag is
  1184.              * set.
  1185.              */
  1186.             dbgStackLength = savedDbgStackLength;
  1187.             excStackLength = savedExcStackLength;
  1188.             bcopy((Address)&savedDbgStack, (Address)&dbgGlobalStack,
  1189.                 sizeof(dbgGlobalStack));
  1190.             callInProgress = FALSE;
  1191.         }
  1192.         /*
  1193.          * Dump the syslog buffer.
  1194.          */
  1195.         Dev_SyslogReturnBuffer(&buffer, &firstIndexPtr,
  1196.                        &lastIndexPtr, &bufSize);
  1197.         if (*firstIndexPtr == -1) {
  1198.             length = 0;
  1199.             PutReplyBytes(4, (Address) &length);
  1200.             dbg_UsingSyslog = FALSE;
  1201.         } else if (*firstIndexPtr <= *lastIndexPtr) {
  1202.             length = *lastIndexPtr - *firstIndexPtr + 1;
  1203.             if (length + 4 > PACKET_DATA_SIZE) {
  1204.             length = PACKET_DATA_SIZE - 4;
  1205.             }
  1206.             PutReplyBytes(4, (Address) &length);
  1207.             PutReplyBytes(length,
  1208.                   (Address)&buffer[*firstIndexPtr]);
  1209.             *firstIndexPtr += length;
  1210.             if (*firstIndexPtr > *lastIndexPtr) {
  1211.             *firstIndexPtr = *lastIndexPtr = -1;
  1212.             }
  1213.         } else {
  1214.             length = bufSize - *firstIndexPtr;
  1215.             if (length + 4 > PACKET_DATA_SIZE) {
  1216.             length = PACKET_DATA_SIZE - 4;
  1217.             }
  1218.             PutReplyBytes(4, (Address) &length);
  1219.             PutReplyBytes(length,
  1220.                   (Address)buffer[*firstIndexPtr]);
  1221.             *firstIndexPtr += length;
  1222.             if (*firstIndexPtr == bufSize) {
  1223.             *firstIndexPtr = 0;
  1224.             }
  1225.         }
  1226.         SendReply();
  1227.         break;
  1228.         }
  1229.         case DBG_CALL_FUNCTION: {
  1230.         Dbg_CallFunc        callFunc;
  1231.         int            returnVal;
  1232.         static int        argBuf[128];
  1233.         GetRequestBytes(2 * sizeof(int), (Address) &callFunc);
  1234.         if (dbgTraceLevel >= 2) {
  1235.             printf("Addr=%x Numbytes=%d ",
  1236.                 callFunc.address, callFunc.numBytes);
  1237.         }
  1238.  
  1239.         if ((callFunc.numBytes >= 0 && callFunc.numBytes < 128) &&
  1240.              Dbg_InRange((unsigned int) callFunc.address,4,FALSE)) {
  1241.             GetRequestBytes(callFunc.numBytes,(Address) argBuf);
  1242.             returnVal = (* ((int (*)()) callFunc.address))(argBuf[0],
  1243.             argBuf[1],argBuf[2],argBuf[3],argBuf[4],argBuf[5],argBuf[6],
  1244.             argBuf[7],argBuf[8],argBuf[9]);
  1245.         } else {
  1246.  
  1247.             if (dbgTraceLevel >= 2) {
  1248.             printf("FAILURE ");
  1249.             }
  1250.             GetRequestBytes(callFunc.numBytes,(Address)argBuf);
  1251.             returnVal = -1;
  1252.         }
  1253.         PutReplyBytes(4, (char *) &returnVal);
  1254.         SendReply();
  1255.  
  1256.         break;
  1257.         }
  1258.         case DBG_CONTINUE: 
  1259.         /*
  1260.          * The client wants to continue execution.
  1261.          */
  1262.         GetRequestBytes(sizeof(int), 
  1263.                 (Address) &dbgGlobalStack.trapStack.excStack.pc);
  1264.         if (dbgTraceLevel >= 2) {
  1265.             printf("Continuing from pc %x ",
  1266.                 dbgGlobalStack.trapStack.excStack.pc);
  1267.         }
  1268.          {
  1269.             int    dummy;
  1270.  
  1271.             PutReplyBytes(4, (Address) &dummy);
  1272.             SendReply();
  1273.         }
  1274.  
  1275.         dbg_BeingDebugged = TRUE;
  1276.         done = TRUE;
  1277.         break;
  1278.  
  1279.         case DBG_SINGLESTEP:
  1280.         /*
  1281.          * The client wants to single step.
  1282.          */
  1283.         GetRequestBytes(sizeof(int), 
  1284.                 (Address) &dbgGlobalStack.trapStack.excStack.pc);
  1285.         if (dbgTraceLevel >= 2) {
  1286.             printf("Stepping from pc %x ",
  1287.                 dbgGlobalStack.trapStack.excStack.pc);
  1288.         }
  1289.          {
  1290.             int    dummy;
  1291.  
  1292.             PutReplyBytes(4, (Address) &dummy);
  1293.             SendReply();
  1294.         }
  1295.  
  1296.         /* 
  1297.          * Turn the trace bit on in the SR.
  1298.          */
  1299.         dbgGlobalStack.trapStack.excStack.statusReg |= 
  1300.                             MACH_SR_TRACEMODE;
  1301.         dbg_BeingDebugged = TRUE;
  1302.         done = TRUE;
  1303.         break;
  1304.  
  1305.         case DBG_DETACH:
  1306.         /*
  1307.          * The debugger has terminated and wants to let us go about our
  1308.          * business.
  1309.          */
  1310.         GetRequestBytes(sizeof(int), 
  1311.                 (Address) &dbgGlobalStack.trapStack.excStack.pc);
  1312.         if (dbgTraceLevel >= 2) {
  1313.             printf("Detaching at pc %x ",
  1314.                 dbgGlobalStack.trapStack.excStack.pc);
  1315.         }
  1316.          {
  1317.             int    dummy;
  1318.  
  1319.             PutReplyBytes(4, (Address) &dummy);
  1320.             SendReply();
  1321.         }
  1322.  
  1323.         dbg_BeingDebugged = FALSE;
  1324.         done = TRUE;
  1325.         printf("Sprite is now detached from the debugger\r\n");
  1326.         break;
  1327.  
  1328.         case DBG_UNKNOWN:
  1329.         printf("debugger: unrecognized request\n");
  1330.         break;
  1331.     }
  1332.  
  1333.     if (dbgTraceLevel >= 2) {
  1334.         printf("\r\n");
  1335.     }
  1336.     if (!done) {
  1337.         (void)ReadRequest(FALSE);
  1338.         GetRequestBytes(2, (Address)&tOpcode);
  1339.         opcode = (Dbg_Opcode) tOpcode;
  1340.     }
  1341.     }
  1342.  
  1343.     /*
  1344.      * Return from the debugger.  Before we return, we must push the trap
  1345.      * stuff back onto the stack and restore the saved sp to point to the
  1346.      * exception stuff on the stack.
  1347.      */
  1348.  
  1349.     dbgSavedSP = dbgGlobalStack.gprs[SP] - dbgStackLength;
  1350.     dbgGlobalStack.gprs[SP] -= excStackLength + STACK_INC  +
  1351.                       MACH_TRAP_INFO_SIZE;
  1352.     bcopy((Address) &dbgGlobalStack, (Address) dbgSavedSP, dbgStackLength);
  1353.  
  1354.     VmMachSetKernelContext(oldContext);
  1355.     mach_AtInterruptLevel = atInterruptLevel;
  1356.     dbg_UsingNetwork = FALSE;
  1357.  
  1358.     /*
  1359.      * Don't force system log output to the console.
  1360.      */
  1361.     if (!syslogDiverted) {
  1362.     Dev_SyslogDebug(FALSE);
  1363.     }
  1364. #ifdef sun3
  1365.     /*
  1366.      * Turn off non-maskable interrupts.
  1367.      */
  1368.     Mach_MonStopNmi();
  1369. #endif
  1370. }
  1371.